<template>
  <div class="drag-area" @drop="handleDrop" @dragover="$event.preventDefault()" @dragenter="$event.preventDefault()">
    <p>请将图片拖动到此处</p>
    <p>支持的文件类型包括.jpg/.png/.gif/.jpeg/.webp</p>
    <p>最大上传文件大小为1M</p>
  </div>
  <el-button type="primary" @click="handleUploadFile">选择文件</el-button>
  <el-button type="primary" @click="handleUploadFolder">选择文件夹</el-button>

  <el-table :data="files" style="width: 100%" border stripe>
    <el-table-column prop="name" label="文件名" header-align="center" align="center" border></el-table-column>
    <el-table-column prop="type" label="类型" header-align="center" align="center"></el-table-column>
    <el-table-column prop="size" label="大小" header-align="center" align="center">
      <template #default="scope">{{ formatSize(scope.row.size) }}</template>
    </el-table-column>
    <el-table-column prop="status" label="状态" header-align="center" align="center">
      <template #default="scope">
        <div v-if="scope.row.status === '上传中'">
          <input type="range" min="0" max="100" :value="scope.row.process" disabled>
          <span>{{ scope.row.process }}%</span>
        </div>
        <div v-else>{{ scope.row.status }}</div>
      </template>
    </el-table-column>
    <el-table-column label="操作" header-align="center" align="center">
      <template #default="scope">
        <button v-if="scope.row.status === '等待上传'" @click="upload(scope.row,scope.$index)">上传</button>
        <button v-else-if="scope.row.status === '上传中'" class="disabled">上传中</button>
        <button v-else @click="download(scope.row.url)" class="download">下载</button>
      </template>
    </el-table-column>
  </el-table>
  <el-tag type="primary" effect="plain">文件数量: {{ files.length }}</el-tag>
  <el-tag type="success">成功上传:{{ computedSuccessNum }}</el-tag>
  <el-tag type="primary">文件总大小:{{ formatSize(computedTotalSize) }}</el-tag>
  <el-button type="primary" v-if="files.some(file => file.status === '等待上传')" @click="uploadAll">一键上传</el-button>
</template>

<script lang="ts" setup>
import axios from 'axios';
import { createCollectionWithScope } from 'element-plus/es/components/collection';
import { onMounted, ref, computed } from 'vue'
// 定义可接受文件类型
const validTypes = ['jpg', 'png', 'gif', 'jpeg', 'webp'];
const files = ref([])

// 拖拽行为
const handleDrop = (e) => {
  // 阻止默认行为
  e.preventDefault()
  // 收集移动的文件
  let dragfiles = [...e.dataTransfer.files]
  // 检查文件大小
  if (dragfiles.some(file => file.size > 1024 * 1024)) {
    return alert('文件大小不能超过1M')
  } else {
    if (dragfiles.some(file => !validTypes.includes(file.type.split('/')[1]))) {
      return alert('文件类型不支持')
    } else {
      console.log('成功拖拽文件', dragfiles)
      filesPush(dragfiles)
    }
  }
}

// 格式化大小
const formatSize = (size) => {
  if (size < 1024) {
    return size + 'B'
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + 'KB'
  } else if (size < 1024 * 1024 * 1024) {
    return (size / 1024 / 1024).toFixed(2) + 'MB'
  } else {
    return (size / 1024 / 1024 / 1024).toFixed(2) + 'GB'
  }
}
// 文件传入files数组,检查文件类型及大小
const filesPush = (arr) => {
  const errFiles = arr.filter((file) => file.size > 1024 * 1024)
  if (errFiles.length) {
    alert(`文件${errFiles.map(file => file.name).join(',')}大小不能超过1M`)
  }
  arr.filter(file => validTypes.includes(file.type.split('/')[1]) && file.size <= 1024 * 1024)
  .forEach(file => {
    files.value.push({
      name: file.name,
      type: file.type.split('/')[1],
      size: file.size,
      status: '等待上传',
      file: file,
      process:0,
      url: ''
    })
  })
}

// 创建全局input元素
const input = document.createElement('input')
input.style.display = 'none'
input.type = 'file'
input.multiple = true
// 上传文件
const handleUploadFile = () => {
  input.webkitdirectory = false
  input.accept = '.jpg,.png,.gif,.jpeg,.webp'
  input.onchange = (e) => {
    console.log('成功选择文件', e.target.files)
    filesPush([...e.target.files])
  }
  // 触发文件选择器
  input.click()
}
// 上传文件夹
const handleUploadFolder = () => {
  input.webkitdirectory = true
  input.onchange = (e) => {
    filesPush([...e.target.files]);
  }
  input.click()
}


// 计算总大小
const computedTotalSize = computed(() => {
  return files.value.reduce((acc, cur) => {
    return acc + cur.size
  }, 0)
})
// 计算成功上传个数
const computedSuccessNum = computed(() => {
  return files.value.filter(file => file.status === '上传成功').length
})


// 上传文件
const upload = (file,index) => {
  const url = 'http://localhost:3000/upload'
  // 设置请求头
  // 将文件对象存到formData中
  const formData = new FormData()
  formData.append('file', file.file)
  // 发送axios请求
  axios({
    url: url,
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: (e) => {
      // 更新进度条
      files.value[index].status = '上传中'
      files.value[index].process = ((e.loaded / e.total) * 100).toFixed(2)
    }
  }).then(res => {
    console.log(res)
    if (res.data.code === 200) {
      files.value[index].status = '上传成功'
      files.value[index].url = res.data.url
    } else {
      files.value[index].status = '上传失败'
    }
  }).catch(err => {
    files.value[index].status = '上传失败'
  })
}

// 上传所有文件
const uploadAll = () => {
  files.value.forEach((file,index) => {
    if (file.status === '等待上传') {
      upload(file,index)
    }
  })
}

// 下载文件
const download = (url) => {
  console.log(url)
  // 获得存储至本地的url中的文件名
  const filename = url.split('/')[4]
  // 在前端实现下载
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
}


</script>

<style lang="scss">
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.drag-area {
  width: 100%;
  height: 150px;
  border: 2px dashed #ccc;
  text-align: center;
  padding: 10px;
  margin-bottom: 5px;

  p {
    margin-top: 10px;
    color: #888;
  }
}

.el-table {
  margin: 20px 0;

  button {
    all: unset;
    width: 50px;
    padding: 3px;
    border: 1px solid #ccc;
    border-radius: 5px;
    background-color: #409eff;
    color: #fff;
    cursor: pointer;
    &.disabled {
      background-color: #ccc;
      cursor: not-allowed;
    }
    &.download {
      background-color: #67c23a;
    }
  }
}

.el-tag {
  margin-right: 10px;
  font-size: 16px;
}
</style>